package com.song.api.gateway.filter;

import javax.servlet.http.HttpServletRequest;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

/**
 * 
 * @description : 在实现了自定义过滤器之后，它并不会直接生效，我们还需要为其创建具体的Bean才能启动该过滤器，比如，在应用主类中增加.
 * 
 * 读者可以根据自己的需要在服务网关上定义一些与业务无关的通用逻辑实现对请求的过滤和拦截，比如：签名校验、权限校验、请求限流等功能。
 * 
 * @date        : 2018-08-14 11:43
 * @author      : leoSong
 *
 */
public class AccessFilter extends ZuulFilter {

  /**
   * 过滤器的具体逻辑。这里我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求，不对其进行路由，然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码，
   * 当然我们也可以进一步优化我们的返回，比如，通过ctx.setResponseBody(body)对返回body内容进行编辑等。
   */
  @Override
  public Object run() throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    System.out.println("send {} request to {}" + request.getMethod() + request.getRequestURL().toString());

    Object accessToken = request.getParameter("accessToken");
    if (accessToken == null) {
      System.out.println("access token is empty");
      ctx.setSendZuulResponse(true);
      ctx.setResponseStatusCode(401);
      ctx.setResponseBody("access token is empty---setResponseBody");
      return "access token is empty---return";
    }
    System.out.println("access token ok");
    return "access token is empty";
  }
  
  
/**
 * 判断该过滤器是否需要被执行。这里我们直接返回了true，因此该过滤器对所有请求都会生效。实际运用中我们可以利用该函数来指定过滤器的有效范围。
 */
  @Override
  public boolean shouldFilter() {
    return true;
  }

  
  /**
   * 过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时，需要根据该方法返回的值来依次执行。
   * 
   * 通过int值来定义过滤器的执行顺序，数值越小优先级越高。
   */
  @Override
  public int filterOrder() {
    return 0;
  }

  
  /**
   * 过滤器的类型，它决定过滤器在请求的哪个生命周期中执行。这里定义为pre，代表会在请求被路由之前执行。
   * 
   * pre：可以在请求被路由之前调用。routing：在路由请求时候被调用。post：在routing和error过滤器之后被调用。error：处理请求时发生错误时被调用。
   */
  @Override
  public String filterType() {
    return "pre";
  }

}
